#include "stdafx.h"
#include "Quad.h"

#include "ContentManager.h"

namespace Framework {

Quad::Quad(Game* game) : Mesh(game) {
    this->alpha = 1;
    this->billboard = false;
    this->mesh = NULL;
    this->SetCullMode(D3DCULL_NONE);
}

Quad::~Quad(void) {
    if (this->mesh != NULL) {
        d3d::Delete(this->mesh);
    }
}

FLOAT Quad::GetAlpha() const {
    return this->alpha;
}

void Quad::SetAlpha(FLOAT val) {
    this->alpha = val;
}

bool Quad::GetBillboard() const {
    return this->billboard;
}

void Quad::SetBillboard(bool val) {
    this->billboard = val;
}

D3DXMATRIX Quad::GetWorldMatrix() {
    if (!this->billboard) {
        return __super::GetWorldMatrix();
    }

    D3DXMATRIX billboardMatrix;
    D3DXMATRIX v = this->GetGame()->GetCamera()->GetViewMatrix();
    D3DXMatrixInverse(&billboardMatrix, NULL, &this->GetGame()->GetCamera()->GetViewMatrix());

    billboardMatrix._41 = 0.0f;
    billboardMatrix._42 = 0.0f;
    billboardMatrix._43 = 0.0f;

    D3DXVECTOR3 scale = this->GetScale();
    D3DXMATRIX scaleMatrix;
    D3DXMatrixScaling(&scaleMatrix, scale.x, scale.y, scale.z);

    D3DXVECTOR3 position = this->GetPosition();
    D3DXMATRIX translationMatrix;
    D3DXMatrixTranslation(&translationMatrix, position.x, position.y, position.z);

    return (scaleMatrix  * this->rotationMatrix * billboardMatrix) * translationMatrix;
}

void Quad::GenerateMesh() {
    ID3DXMesh* mesh;
    D3DXCreateMeshFVF(
        2,
        4,
        D3DXMESH_MANAGED,
        Vertex::FVF,
        this->GetGame()->GetGraphicsDevice(),
        &mesh);

    Vertex* vertices = NULL;
    mesh->LockVertexBuffer(0, (void**)&vertices);
    memcpy(vertices, &this->vertices[0], sizeof(Vertex) * this->vertices.size());
    mesh->UnlockVertexBuffer();

    DWORD* indices = 0;
    mesh->LockIndexBuffer(0, (void**)&indices);
    memcpy(indices, &this->indices[0], sizeof(WORD) * this->indices.size());
    mesh->UnlockVertexBuffer();

    DWORD* attributeBuffer = 0;
    mesh->LockAttributeBuffer(0, &attributeBuffer);
    attributeBuffer[0] = 0;
    attributeBuffer[1] = 0;
    mesh->UnlockAttributeBuffer();

    DWORD* adjacencyBuffer = new DWORD[mesh->GetNumFaces() * 3];
    HRESULT hr = mesh->GenerateAdjacency(0.0f, adjacencyBuffer);
    mesh->OptimizeInplace(
        D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE,
        adjacencyBuffer,
        NULL, NULL, NULL);

    delete [] adjacencyBuffer;
    this->mesh = new D3DXMesh(mesh);
    this->mesh->GetMaterials()->push_back(d3d::WHITE_MTRL);
    IDirect3DTexture9* texture = this->GetGame()->GetContentManager()->LoadTexture("particle.dds");
    this->mesh->GetTextures()->push_back(texture);
}

void Quad::Initialize() {
    this->vertices.push_back(Vertex(-1, -1, 0, 0, 0, -1, 0, 1));
    this->vertices.push_back(Vertex(-1, 1, 0, 0, 0, -1, 0, 0));
    this->vertices.push_back(Vertex(1, 1, 0, 0, 0, -1, 1, 0));
    this->vertices.push_back(Vertex(1, -1, 0, 0, 0, -1, 1, 1));

    this->indices.push_back(0);
    this->indices.push_back(1);
    this->indices.push_back(2);
    this->indices.push_back(0);
    this->indices.push_back(2);
    this->indices.push_back(3);

    __super::Initialize();
}

void Quad::LoadContent() {
    this->GenerateMesh();
    __super::LoadContent();
}

}
